---
layout: docs
page_title: TCP - Listeners - Configuration
description: |-
  The TCP listener configures Boundary to listen on the specified TCP address and
  port.
---

# `tcp` Listener

The TCP listener configures Boundary to listen on a TCP address/port.

```hcl
listener "tcp" {
  purpose = "api"
  address = "127.0.0.1:9200"
}
```

The `listener` stanza may be specified more than once to make Boundary listen on
multiple interfaces; however, only one listener marked for `cluster` purpose is
allowed.

## Listener's custom response headers

Boundary supports defining custom HTTP response headers for all requests on any Boundary controller.
Headers are defined based on the returned status code. For example, you can define a list of
custom response headers for the `200` status code, and another list of custom response headers for
the `307` status code, and so on. You can also define headers based on the hundred-level status
code. For example, a list of headers applied to the `4xx` code will be applied to 400, 401, 404, and
all other 400-level status codes. The more specific the status, the higher priority it has.
Default headers are overwritten by hundred-level headers, which are overwritten by status-specific
headers.

There are two different config parameters that define headers: `custom_api_response_headers` and
`custom_ui_response_headers`. API headers apply to API endpoints, currently all paths starting
with `/v1/`. UI headers apply to all other paths. This allows for configuring headers specifically
for serving content to a web browser, such as CSP headers.

## `tcp` Listener Parameters

### General

- `purpose` `(string: "")` - Specifies the purpose. Can be `api`, `cluster`,
  `proxy`, or `ops`.

- `address` `(string: "127.0.0.1:9200")` – Specifies the address to bind to for
  listening.

- `http_idle_timeout` `(string: "5m")` - Specifies the maximum amount of time to
  wait for the next request when keep-alives are enabled. If `http_idle_timeout`
  is zero, the value of `http_read_timeout` is used. If both are zero, the value
  of `http_read_header_timeout` is used. This is specified using a label suffix
  like `"30s"` or `"1h"`.

- `http_read_header_timeout` `(string: "10s")` - Specifies the amount of time
  allowed to read request headers. This is specified using a label suffix like
  `"30s"` or `"1h"`.

- `http_read_timeout` `(string: "30s")` - Specifies the maximum duration for
  reading the entire request, including the body. This is specified using a
  label suffix like `"30s"` or `"1h"`.

- `http_write_timeout` `string: "0")` - Specifies the maximum duration before
  timing out writes of the response and is reset whenever a new request's header
  is read. The default value of `"0"` means infinity. This is specified using a
  label suffix like `"30s"` or `"1h"`.

<!-- We don't have this implemented yet
- `max_request_size` `(int: 33554432)` – Specifies a hard maximum allowed
  request size, in bytes. Defaults to 32 MB. Specifying a number less than or
  equal to `0` turns off limiting altogether.
!-->

- `max_request_duration` `(string: "90s")` – Specifies the maximum
  request duration allowed before Boundary cancels the request. This overrides
  `default_max_request_duration` for this listener.

- `cors_enabled` `(boolean: true)` - Specifies if CORS should be enabled, which
  allows Boundary to support external browser-based clients (not including admin
  UI), such as Boundary Desktop. If not specified, CORS will be enabled with an
  allowed origin that grants access to Boundary Desktop, unless overridden with
  `cors_disable_default_allowed_origin_values`.

- `cors_disable_default_allowed_origin_values` `(boolean: false)` - Specifies
  that Boundary should not append default allowed origin values to any specified
  in `cors_allowed_origins`, such as Boundary Desktop's origin. This also
  disables the behavior of enabling CORS if `cors_enabled` is not specified.

- `cors_allowed_origins` `(array(string): ["serve://boundary"])` - An array of
  allowed CORS origins. Origins must include protocol, host, and port (if port
  is different than the default for the specified protocol). To allow all
  origins, set to `['*']`. By default, Boundary Desktop's origin
  `serve://boundary` is appended to any values included here, unless
  `cors_disable_default_allowed_origin_values` is specified.

- `cors_allowed_headers` `(array(string): [])` – An array specifying headers
  that are permitted to be on cross-origin requests. Headers set via this
  parameter will be appended to the list of headers that Boundary allows by
  default, such as `"Content-Type"`, `"X-Requested-With"`, and
  `"Authorization"`.

### `custom_api_response_headers` Parameters

- `default` `(key-value-map: {})` - A map of string header names to an array of
  string values. The default headers are set on all endpoints regardless of
  the status code value. For an example, refer to the
  [Configuring custom http response headers](#configuring-custom-http-response-headers)
  section.

- `<collective status code>` `(key-value-map: {})` - A map of string header names
  to an array of string values. These headers are set only when the response status
  code falls under the collective status code.
  For example, `"2xx" = {"Header-A": ["Value1", "Value2"]}`, `"Header-A"`
  is set when the http response status code is `"200"`, `"204"`, etc. This overrides
  headers defined at the `default` level.

- `<specific status code>` `(key-value-map: {})` - A map of string header names
  to an array of string values. These headers are set only when the specific status
  code is returned. For example, `"200" = {"Header-A": ["Value1", "Value2"]}`, `"Header-A"`
  is set when the http response status code is `"200"`. This overrides headers defined at
  the `default` and `collective status code` level.

### `custom_ui_response_headers` Parameters

- `default` `(key-value-map: {})` - A map of string header names to an array of
  string values. The default headers are set on all endpoints regardless of
  the status code value. For an example, refer to the
  [Configuring custom http response headers](#configuring-custom-http-response-headers)
  section.

- `<collective status code>` `(key-value-map: {})` - A map of string header names
  to an array of string values. These headers are set only when the response status
  code falls under the collective status code.
  For example, `"2xx" = {"Header-A": ["Value1", "Value2"]}`, `"Header-A"`
  is set when the http response status code is `"200"`, `"204"`, etc. This overrides
  headers defined at the `default` level.

- `<specific status code>` `(key-value-map: {})` - A map of string header names
  to an array of string values. These headers are set only when the specific status
  code is returned. For example, `"200" = {"Header-A": ["Value1", "Value2"]}`, `"Header-A"`
  is set when the http response status code is `"200"`. This overrides headers defined at
  the `default` and `collective status code` level.

### TLS

~> `tls` parameters are valid for `api` and `ops` listeners. `cluster`
and `proxy` connections use their own ephemeral TLS stacks. For more 
information, see [the connections security concepts
page](/boundary/docs/concepts/security/connections-tls).

- `tls_disable` `(string: "false")` – Specifies if TLS will be disabled. Boundary
  assumes TLS by default, so you must explicitly disable TLS to opt-in to
  insecure communication.

- `tls_cert_file` `(string: <required-if-enabled, reloads-on-SIGHUP>)` –
  Specifies the path to the certificate for TLS. To configure the listener to
  use a CA certificate, concatenate the primary certificate and the CA
  certificate together. The primary certificate should appear first in the
  combined file. On `SIGHUP`, the path set here _at Boundary startup_ will be
  used for reloading the certificate; modifying this value while Boundary is
  running will have no effect for `SIGHUP`s.

- `tls_key_file` `(string: <required-if-enabled, reloads-on-SIGHUP>)` –
  Specifies the path to the private key for the certificate. If the key file is
  encrypted, you will be prompted to enter the passphrase on server startup. The
  passphrase must stay the same between key files when reloading your
  configuration using `SIGHUP`. On `SIGHUP`, the path set here _at Boundary
  startup_ will be used for reloading the certificate; modifying this value
  while Boundary is running will have no effect for `SIGHUP`s.

- `tls_min_version` `(string: "tls12")` – Specifies the minimum supported
  version of TLS. Accepted values are "tls10", "tls11", "tls12" or "tls13".

  !> TLS 1.1 and lower are generally considered insecure.

- `tls_max_version` `(string: "tls13")` – Specifies the maximum supported
  version of TLS, useful if appliances (e.g. load balancers) are not yet capable
  of higher levels. Accepted values are "tls10", "tls11", "tls12" or "tls13".

  !> TLS 1.1 and lower are generally considered insecure.

- `tls_cipher_suites` `(string: "")` – Override the default list of supported
  ciphersuites (which varies by TLS version) with the the specified
  comma-delimited list. The list of all available ciphersuites is available in
  the [Golang TLS documentation][golang-tls].

- `tls_prefer_server_cipher_suites` `(string: "false")` – Specifies to prefer the
  server's ciphersuite over the client ciphersuites.

- `tls_require_and_verify_client_cert` `(string: "false")` – Turns on client
  authentication for this listener; the listener will require a presented
  client cert that successfully validates against system CAs.

- `tls_client_ca_file` `(string: "")` – PEM-encoded Certificate Authority file
  used for checking the authenticity of client.

<!-- Not enabled yet
- `x_forwarded_for_authorized_addrs` `(string: <required-to-enable>)` –
  Specifies the list of source IP CIDRs for which an X-Forwarded-For header
  will be trusted. Comma-separated list or JSON array. This turns on
  X-Forwarded-For support.

- `x_forwarded_for_hop_skips` `(string: "0")` – The number of addresses that will be
  skipped from the _rear_ of the set of hops. For instance, for a header value
  of `1.2.3.4, 2.3.4.5, 3.4.5.6`, if this value is set to `"1"`, the address that
  will be used as the originating client IP is `2.3.4.5`.

- `x_forwarded_for_reject_not_authorized` `(string: "true")` – If set false,
  if there is an X-Forwarded-For header in a connection from an unauthorized
  address, the header will be ignored and the client connection used as-is,
  rather than the client connection rejected.

- `x_forwarded_for_reject_not_present` `(string: "true")` – If set false, if
  there is no X-Forwarded-For header or it is empty, the client address will be
  used as-is, rather than the client connection rejected.

### `telemetry` Parameters

- `unauthenticated_metrics_access` `(string: "false")` - If set to true, allows
  unauthenticated access to the `/v1/sys/metrics` endpoint.
!-->

## `tcp` Listener Examples

### Configuring TLS

This example shows enabling a TLS listener.

```hcl
listener "tcp" {
  purpose = "api"
  tls_cert_file = "/etc/certs/Boundary.crt"
  tls_key_file  = "/etc/certs/Boundary.key"
}
```

### Configuring custom http response headers

This example shows configuring custom http response headers. Operators can configure
`"custom_api_response_headers"` and `"custom_ui_response_headers"` sub-stanzas in the listener stanza to
set custom http headers that are appropriate to their applications. Examples of such headers are
`"Strict-Transport-Security"` and `"Content-Security-Policy"` which are known HTTP headers, and could be
configured to harden the security of an application communicating with the Boundary endpoints. Note that
vulnerability scans often examine such security related HTTP headers. In addition, you can configure
application-specific custom headers. For example, `"X-Custom-Header"` has been configured in the example
below.

```hcl
listener "tcp" {
  custom_api_response_headers {
    "default" = {
      "Strict-Transport-Security" = ["max-age=31536000; includeSubDomains"],
      "X-Custom-Header" = ["Custom Header Default Value"],
    },
    "2xx" = {
      "X-Custom-Header" = ["Custom Header Value 1", "Custom Header Value 2"],
    },
    "301" = {
      "Strict-Transport-Security" = ["max-age=31536000"],
    },
  }
  custom_ui_response_headers {
    "default" = {
      "Strict-Transport-Security" = ["max-age=31536000; includeSubDomains"],
      "Content-Security-Policy" = ["default-src 'none'; script-src 'self'; frame-src 'self'; font-src 'self'; connect-src 'self'; img-src 'self' data:; style-src 'self'; media-src 'self'; manifest-src 'self'; style-src-attr 'self'; frame-ancestors 'self'"],
      "X-Custom-Header" = ["Custom Header Default Value"],
    },
    "2xx" = {
      "X-Custom-Header" = ["Custom Header Value 1", "Custom Header Value 2"],
    },
    "301" = {
      "Strict-Transport-Security" = ["max-age=31536000"],
      "Content-Security-Policy" = ["default-src 'none'; script-src 'none'; connect-src 'none'"],
    },
  }
}
```

In situations where a header is defined under several status code subsections,
Boundary returns the header matching the most specific response code. For example,
with the config example below, a `307` response would return `307 Custom header value`,
while a `306` would return `3xx Custom header value`.

```hcl
listener "tcp" {
  custom_api_response_headers {
    "default" = {
       "X-Custom-Header" = ["default Custom header value"]
    },
    "3xx" = {
       "X-Custom-Header" = ["3xx Custom header value"]
    },
    "307" = {
       "X-Custom-Header" = ["307 Custom header value"]
    }
  }
}
```

There may also be situations where default or collective status headers have been defined,
but you do not want them returned for a specific status code. You can unset headers at any
level by defining the headers as an empty list.

```hcl
listener "tcp" {
  custom_api_response_headers {
    "default" = {
       "X-Custom-Header" = ["default Custom header value"]
    },
    "3xx" = {
       "X-Custom-Header" = ["3xx Custom header value"]
    },
    "307" = {
		// Do not return this header for 307 responses
       "X-Custom-Header" = []
    }
  }
}
```

### Listening on Multiple Interfaces

This example shows Boundary listening on a private interface, as well as localhost.

```hcl
listener "tcp" {
  purpose = "api"
  address = "127.0.0.1:9200"
}

listener "tcp" {
  purpose = "cluster"
  address = "10.0.0.5:9201"
}
```

[golang-tls]: https://golang.org/src/crypto/tls/cipher_suites.go
[api-addr]: /boundary/docs/configuration#api_addr
[cluster-addr]: /boundary/docs/configuration#cluster_addr
